/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package util;

public class MultMatrix{
	public static int n = 512;
	float[][] a;
	float[][] b;
	float[][] c;

	float[] d;
	float[] e;
	float[] f;

   public static float[] mult(float[] m1, float[] m2, int n) {
        float[] m3 = new float[m1.length];
        float sum = 0;
        /* ijk */
        for (int i = n; --i >=0 ; ) {
            for (int j = n; --j>=0; ) {
                for (int k = n; --k >=0 ; ) {
                    sum += m1[i * n + k] * m2[k * n + j];
                }
                m3[i * n + j] = sum;
            }
        }
        return m3;
    }

	public MultMatrix(){

		a = new float[n][n];
		b = new float[n][n];
		c = new float[n][n];

		d = new float[n*n];
		e = new float[n*n];
		f = new float[n*n];
	}

	public static void calculInutile(){
		double a = Math.random();
		double b ;


		b = Math.cbrt(a);
		a = Math.atan(b);
		b = Math.expm1(a);
		System.out.println(a +" "+ b);
	}
	public void multIjk(){
		float sum = 0;
		/* ijk */
    	for (int i=0; i<n; i++)  {
    		for (int j=0; j<n; j++) {
    			for (int k=0; k<n; k++){
    				sum += a[i][k] * b[k][j];
    			}
    				c[i][j] = sum;
    		}
    	}
	}

	public void init(){

		for (int i=0;i<n;i++)
		{for (int j=0;j<n;j++)
			{
			d[i*n+j]=i+j;
			e[i*n+j]=i-j;
			}
		}

	}

	public void multIjk2(){


		float sum = 0;
		/* ijk */
    	for (int i = n; --i >=0 ; ) {
            for (int j = n; --j>=0; ) {
                for (int k = n; --k >=0 ; ) {
    				sum += d[i*n+k] * e[k*n+j];
    			}
    			f[i*n+j] = sum;
    		}
    	}
	}

	public void multIkj(){
	float r;
		/* ikj */
	for (int i=0; i<n; i++) {
		for (int k=0; k<n; k++) {
			r = a[i][k];
			for (int j=0; j<n; j++) c[i][j] += r * b[k][j];
		}
	}
	}
	public void multIkj2(){
		float r;
			/* ikj */
		for (int i=0; i<n; i++) {
			for (int k=0; k<n; k++) {
				r = d[i*n+k];
				for (int j=0; j<n; j++) f[i*n+j] += r * e[k*n+j];
			}
		}
		}

	public void testIjk(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIjk();
        long after = System.currentTimeMillis();
        long loopTime = after - before;
        System.out.println("ijk time: " +
                           Long.toString(loopTime) +
                           " milliseconds");
	}

	public void testIkj(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIkj();
        long after = System.currentTimeMillis();
        long loopTime = after - before;
        System.out.println("ikj time: " +
                           Long.toString(loopTime) +
                           " milliseconds");
	}

	public void testIjk2(){
		init();
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIjk2();
        long after = System.currentTimeMillis();
        long loopTime = after - before;
        System.out.println("ijk2 time: " +
                           Long.toString(loopTime) +
                           " milliseconds");
	}

	public void testIkj2(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIkj2();
        long after = System.currentTimeMillis();
        long loopTime = after - before;
        System.out.println("ikj2 time: " +
                           Long.toString(loopTime) +
                           " milliseconds");
	}

	public long tpsIjk(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIjk();
        long after = System.currentTimeMillis();
        return after - before;
	}

	public long tpsIkj(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIkj();
        long after = System.currentTimeMillis();
        return after - before;
	}

	public long tpsIjk2(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIjk2();
        long after = System.currentTimeMillis();
        return after - before;
	}

	public long tpsIkj2(){
		// First, figure out the time for an empty loop
        long before = System.currentTimeMillis();
        multIkj2();
        long after = System.currentTimeMillis();
        return after - before;
	}

	public static void main(String[] args) {
		MultMatrix m = new MultMatrix();

    	double alea=0.0;
    	int index;

    	long[] tps = new long[4];
    	long[] nbr = new long[4];
    	for(int i = 0; i<4;i++){
    		tps[i]=0;
    		nbr[i]=0;
    	}

    	m.testIjk2();
    	m.testIkj2();
    	m.testIjk();
    	m.testIkj();
    	System.out.println();
    	m.testIjk2();
    	m.testIkj2();
    	m.testIjk();
    	m.testIkj();
    	System.out.println();
    	m.testIjk2();
    	m.testIkj2();
    	m.testIjk();
    	m.testIkj();
    	System.out.println();
		for(int i =0; i < 16; i++){

			alea = Math.random();
			index = (int)(alea*4);
			//*
			switch(index){
			case 0: tps[0] += m.tpsIjk2(); nbr[0] += 1;
			break;
			case 1: tps[1] += m.tpsIkj2(); nbr[1] += 1;
			break;
			case 2: tps[2] += m.tpsIjk(); nbr[2] += 1;
			break;
			case 3: tps[3] += m.tpsIkj(); nbr[3] += 1;
			break;
			}
			//*/
			/*
			tps[0] += m.tpsIjk2();
			tps[1] += m.tpsIkj2();
			tps[2] += m.tpsIjk();
			tps[3] += m.tpsIkj();
			*/
			//calculInutile();


		}

		for(int i = 0; i<4;i++){
			switch(i){
			case 0: System.out.println("IJK2: ");
			break;
			case 1: System.out.println("IKJ2: ");
			break;
			case 2: System.out.println("IJK: ");
			break;
			case 3: System.out.println("IKJ: ");
			break;
			}
    		System.out.println(tps[i]/nbr[i]);
    		System.out.println();
    		}

	}

}
